<template>
  <el-select
    v-model="form[item.key]"
    :placeholder="placeholder"
    :loading="loading"
    :remote="!!item.remoteMethod"
    :remote-method="remoteMethod"
    :style="style"
    :multiple="item.multiple"
    :disabled="itemDisabled || remoteMethodDisabled"
    :collapse-tags="item.collapseTags"
    @change="change"
    clearable
    filterable
  >
    <div v-infinite-scroll="loadNextPage" :infinite-scroll-immediate="false">
      <el-option
        v-for="{ itemText, itemValue, disabled } of option"
        :key="itemValue"
        :label="itemText"
        :value="itemValue"
        :disabled="disabled"
      />
    </div>
  </el-select>
</template>

<script lang="ts">
import { defineComponent, PropType, ref, watch, onMounted, nextTick } from 'vue'
import { Option, Select } from '../types'
import { get, find, forEach, map, has, isEmpty } from 'lodash'
import usePlaceholder from '@/hooks/usePlacehoder'
import useSearch from '@/hooks/useSearch'
import { FormItemKey, ObjectType } from 'typings/interfaces'
import useDisabled from '../hooks/useDisabled'
import useFilterOption from '../hooks/useFilterOption'
import { OperateTypes } from '@/enums/operateTypes'
import { useRouter } from 'vue-router'

export default defineComponent({
  props: {
    item: {
      type: Object as PropType<Select>,
      required: true,
    },
    form: {
      type: Object as PropType<ObjectType>,
      required: true,
    },
    placeholderId: {
      type: String,
      default: 'lang.placeholder.select',
    },
    filterOptions: {
      type: Object as PropType<ObjectType>,
      default: () => ({}),
    },
    options: {
      type: Object as PropType<Record<FormItemKey, Option[]>>,
      required: true,
    },
    disabled: {
      type: Boolean,
      required: true,
    },
    operateType: {
      type: String as PropType<OperateTypes | null>,
      required: true,
    },
  },
  setup(props) {
    const placeholder = usePlaceholder(props.item, 'lang.placeholder.select')
    const itemDisabled = ref()

    if (props.operateType === OperateTypes.EDIT && props.item.editable === false) {
      // 如果是不可编辑
      itemDisabled.value = true
    } else {
      itemDisabled.value = useDisabled(props.disabled, props.item.disabled)
    }
    const key = get(props, 'item.alias') ?? get(props, 'item.key', '')
    const loading = ref(false)
    const { changePage, pagination, dataSource } = useSearch(props.item?.remoteMethod, {
      pageSize: 100,
    })
    const option = ref<Option[]>(get(props.options, [props.item.key], []))
    const Router = useRouter()

    // 更新option
    watch(
      () => props.options[props.item.key],
      (state) => {
        option.value = state
        if (key == 'facalitiesType' && Router.currentRoute.value.params.facilitiesType) {
          props.form.facalitiesType = Router.currentRoute.value.params.facilitiesType
        }
      }
    )
    //筛选option
    if (props.item.linkage) {
      useFilterOption({
        option,
        dictMap: props.item.linkage.dictMap,
        primevalOption: get(props.options, [props.item.key], []),
        key: key,
        form: props.form,
        watchKey: props.item.linkage.key,
      })
    }

    //筛选option 异步请求
    if (props.item.linkageSync) {
      const linkageSync = {
        watchKey: props.item.linkageSync.key,
        dictMap: props.item.linkageSync.dictMap,
        label: props.item.linkageSync.label || 'label',
        value: props.item.linkageSync.value || 'value',
      }
      watch(
        () => props.form[linkageSync.watchKey],
        (value) => {
          loading.value = true
          linkageSync.dictMap(value).then((dictMapValue) => {
            loading.value = false
            if (dictMapValue.status === 200 && dictMapValue.data.code === 200) {
              option.value = map(dictMapValue.data.data, (d) => ({
                ...d,
                itemText: d[linkageSync.label],
                itemValue: d[linkageSync.value],
              }))
              if (props.form[key]) {
                const rst = find(option.value, { itemValue: props.form[key] })
                if (!rst) {
                  props.form[key] = ''
                }
              }
            }
          })
        },
        { immediate: !isEmpty(props.form[linkageSync.watchKey]) }
      )
    }

    const remoteMethodDisabled = ref(false)
    if (has(props.item, 'remoteMethod')) {
      remoteMethodDisabled.value = true
    }
    watch(dataSource, (state) => {
      if (pagination.pageNum === 1) {
        option.value = map(state, (item) => ({
          ...item,
          itemText: item[key],
          itemValue: item[key],
        }))

        if (props.operateType === OperateTypes.ADD) {
          props.form[props.item.key] = option.value[0].itemValue
          change(props.form[props.item.key])
        }
      } else {
        option.value = [
          ...option.value,
          ...map(state, (item) => ({
            ...item,
            itemText: item[key],
            itemValue: item[key],
          })),
        ]
      }
      remoteMethodDisabled.value = false
    })

    const remoteMethod = (value: string) => {
      loading.value = true
      changePage(1, { [props.item.key]: value })
        .then(() => (loading.value = false))
        .catch(() => (loading.value = false))
    }

    /* 加载下一页 */
    const loadNextPage = () => {
      const { pageNum, pageSize, total } = pagination
      if (pageNum * pageSize < total) {
        changePage(pageNum + 1, { [props.item.key]: props.form[props.item.key] })
      }
    }
    // 动态修改数据后回显数据
    const dynamic = () => {
      for (let item in option.value) {
        if (option.value[item].itemValue == props.form[key]) {
          props.options.assetTypeSmall = [
            ...map(option.value[item].children, (item) => ({
              ...item,
              itemText: item.itemText,
              itemValue: item.itemValue,
            })),
          ]
        }
      }
    }

    onMounted(() => {
      if (key == 'assetTypeBig') {
        dynamic()
      }
    })
    // 动态修改其他表单项
    const change = (value: string) => {
      if (key == 'assetTypeBig') {
        dynamic()
      } else {
        const row = find(option.value, { [key]: value })
        forEach(props.item.shouldUpdate, ([key, alias]) => {
          props.form[key] = get(row, alias ?? key)
        })
      }
    }

    return {
      style: {
        width: props.item?.width ? props.item.width + 'px' : '100%',
      },
      option,
      loading,
      remoteMethod,
      placeholder,
      loadNextPage,
      change,
      itemDisabled,
      remoteMethodDisabled,
    }
  },
})
</script>
